package clause

import (
	"fmt"
	"strings"
)

type generator func(values ...interface{}) (string, []interface{})

var generators map[Type]generator

func init() {
	generators = make(map[Type]generator)
	generators[INSERT] = _insert
	generators[VALUES] = _values
	generators[SELECT] = _select
	generators[LIMIT] = _limit
	generators[OFFSET] = _offset
	generators[WHERE] = _where
	generators[GROUPBY] = _groupBy
	generators[ORDERBY] = _orderBy
	generators[HAVING] = _having
	generators[UPDATE] = _update
	generators[DELETE] = _delete
	generators[COUNT] = _count
	generators[OR] = _or
	generators[JOIN] = _join

}

func genBindVars(num int) string {
	var vars []string
	for i := 0; i < num; i++ {
		vars = append(vars, "?")
	}
	return strings.Join(vars, ", ")
}

func _insert(values ...interface{}) (string, []interface{}) {
	// INSERT INTO $tableName ($fields)
	tableName := values[0]
	fields := strings.Join(values[1].([]string), ",")
	return fmt.Sprintf("INSERT INTO %s (%v)", tableName, fields), []interface{}{}
}

func _values(values ...interface{}) (string, []interface{}) {
	// VALUES ($v1), ($v2), ...
	var bindStr string
	var sql strings.Builder
	var vars []interface{}
	sql.WriteString("VALUES ")
	for i, value := range values {
		v := value.([]interface{})
		if bindStr == "" {
			bindStr = genBindVars(len(v))
		}
		sql.WriteString(fmt.Sprintf("(%v)", bindStr))
		if i+1 != len(values) {
			sql.WriteString(", ")
		}
		vars = append(vars, v...)
	}
	return sql.String(), vars

}

func _select(values ...interface{}) (string, []interface{}) {
	// SELECT $fields FROM $tableName
	tableName := values[0]
	fields := strings.Join(values[1].([]string), ",")
	return fmt.Sprintf("SELECT %v FROM %s", fields, tableName), []interface{}{}
}

func _limit(values ...interface{}) (string, []interface{}) {
	// LIMIT $num
	return "LIMIT ?", values
}

func _offset(values ...interface{}) (string, []interface{}) {
	// LIMIT $num
	return "OFFSET ?", values
}

func _where(values ...interface{}) (string, []interface{}) {
	// WHERE $desc
	desc, vars := values[0], values[1:]

	return fmt.Sprintf("WHERE %s", checkIn(desc, vars)), vars
}

func _orderBy(values ...interface{}) (string, []interface{}) {
	return fmt.Sprintf("ORDER BY %s", values[0]), []interface{}{}
}

func _having(values ...interface{}) (string, []interface{}) {
	desc, vars := values[0], values[1:]
	return fmt.Sprintf("HAVING  %s", desc), vars
}

func _groupBy(values ...interface{}) (string, []interface{}) {
	return fmt.Sprintf("GROUP BY %s", values[0]), []interface{}{}
}

func _update(values ...interface{}) (string, []interface{}) {
	tableName, desc, vars := values[0], values[1], values[2:]

	return fmt.Sprintf("UPDATE %s SET %s", tableName, desc), vars
}

func _delete(values ...interface{}) (string, []interface{}) {
	return fmt.Sprintf("DELETE FROM %s", values[0]), []interface{}{}
}

func _count(values ...interface{}) (string, []interface{}) {
	return _select(values[0], []string{"count(*)"})
}

func _or(values ...interface{}) (string, []interface{}) {
	desc, vars := values[0], values[1:]
	return fmt.Sprintf("OR %s", checkIn(desc, vars)), vars
}

func _join(values ...interface{}) (string, []interface{}) {
	joinT, table, onExpr := values[0], values[1], values[2]
	// INNER JOIN、LEFT JOIN、RIGHT JOIN、FULL JOIN、CROSS JOIN,JION
	// 如果输入 INNER ,LEFT ,RIGHT,FULL,CROSS 则自动在他们后面加上 JOIN
	/*jT := strings.ToUpper(joinT.(string))

	if jT == "INNER" || jT == "LEFT" || jT == "RIGHT" || jT == "FULL" || jT == "CROSS" {
		return fmt.Sprintf("%s JOIN %s ON %s", joinT, table, onExpr), []interface{}{}
	} else {
		return fmt.Sprintf("%s  %s ON %s", joinT, table, onExpr), []interface{}{}
	}
	*/
	return fmt.Sprintf("%s  %s ON %s", joinT, table, onExpr), []interface{}{}
}

func checkIn(desc interface{}, value []interface{}) interface{} {
	// 将 desc 转换成字符串并全部转换为大写字母
	descStr := strings.ToUpper(fmt.Sprintf("%v", desc))
	// 检测字符串中是否包含 "IN"
	if !strings.Contains(descStr, "IN") {
		return desc
	}
	// 查找字符串中是否有问号
	index := strings.Index(descStr, "?")
	if index == -1 {
		return desc
	}
	// 计算需要替换的问号数量
	num := len(value)
	if num == 0 {
		return desc
	}
	marks := ""
	// 使用 strings.Repeat 函数生成问号的数量
	if !strings.Contains(descStr, "(") {
		marks = "(" + strings.Repeat("?,", num-1) + "?)"
	} else {
		marks = strings.Repeat("?,", num-1) + "?"
	}

	// 将问号替换成拼接好的字符串
	descStr = descStr[:index] + marks + descStr[index+1:]
	return descStr
}
